#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/9/22 21:48
# @Author  : Hobe Frank
# @Software: PyCharm
import os
import exifread
import numpy as np
import cv2
import shutil
# import open3d as o3d
class Tools(object):
    def __init__(self):
        super().__init__()

    def joinDir(self,orign_dir,folder_list):
        '''
        将根目录与目录下的文件夹名称进行拼接，将目录下文件夹列表的名称转换为绝对路径
        :param orign_dir: 根目录，是一个字符串
        :param folder_list: 文件列表，是一个list
        :return:绝对路径列表，是一个list
        '''
        return ['\\'.join([orign_dir, i]) for i in folder_list]

    def im_list(self,folder):  #
        '''
        读取文件夹下的图片(jpg、png、bmp)
        :param folder: 文件夹路径str
        :return: img_list 图片列表list
        '''
        folder_list = os.listdir(folder)
        img_list = []
        for i in folder_list:
            if i[-3:] == "jpg" or i[-3:] == "png" or i[-3:] == "bmp" or i[-3:] == "JPG":
                img_list.append(i)
        return img_list
    def get_GPSexif(self,dir):
        '''
        得到图像自带的gps信息
        :param dir: 图像路径str
        :return: 纬度(°)，经度(°)，海拔(m)
        '''
        def read_values(contents,target):
            d,m,s = contents[target].values
            s = float(s)
            value = d + m / 60.0 + s / 3600.0
            return value
        with open(dir,'rb') as fp:
            contents = exifread.process_file(fp)
            lat = read_values(contents,'GPS GPSLatitude')
            if contents['GPS GPSLatitudeRef'].values == 'S':
                lat = -lat
            lon = read_values(contents,'GPS GPSLongitude')
            if contents['GPS GPSLongitudeRef'].values == 'W':
                lon = -lon
            Altitude = float(contents['GPS GPSAltitude'].values[0])
            return lat,lon,Altitude
    def read_pos(self,dir,out_path=''):
        im_list = self.im_list(dir)
        path = self.joinDir(dir,im_list)
        BLH = np.array(list(map(self.get_GPSexif,path))).reshape(-1,3)
        NBLH = np.concatenate([np.array(im_list).reshape(-1,1),BLH],axis=1)
        with open(dir+'\\pos.txt','w') as fp:
            np.savetxt(fp,NBLH,fmt = '%s    %15.7lf %15.7lf %10.2lf',header='name   B(°)L(°)H(m)[WGS84]')

    @staticmethod
    def cv_imread(file_path):
        '''
        读取图片（含中文路径）
        :param file_path: 图片路径str
        :return: 图片矩阵np（uint8）
        '''
        cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
        return cv_img

    @staticmethod
    def cv_show(name, img):
        '''
        展示图片
        :param name:图窗名str
        :param img: 图片矩阵np（uint8）
        :return:
        '''
        cv2.namedWindow(name, cv2.WINDOW_NORMAL)
        cv2.imshow(name, img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    @staticmethod
    def img_split(img):
        '''
        将图像分割为4块
        -------------------------------
        |   1   |   2  |   3  |   4   |
        |       |      |      |       |
        | ------|------|------|-------|
        |    5  |   6  |   7  |   8   |
        |--------------|------|-------|
        '''
        h,w = img.shape[0:2]
        img_split =[]
        img_split.append(img[:int(h/2),:int(w/4)])#1
        img_split.append(img[:int(h/2),int(w/4):int(w/4)*2])#2
        img_split.append(img[:int(h / 2), int(w / 4) * 2:int(w / 4) * 3])  # 3
        img_split.append(img[:int(h / 2), int(w / 4) * 3:w + 1])  # 4
        img_split.append(img[int(h / 2):h + 1,:int(w / 4)])  # 5
        img_split.append(img[int(h / 2):h + 1, int(w / 4):int(w / 4) * 2])  # 6
        img_split.append(img[int(h / 2):h + 1, int(w / 4) * 2:int(w / 4) * 3])  # 7
        img_split.append(img[int(h / 2):h + 1, int(w / 4) * 3:w + 1])  # 8
        return img_split
    @staticmethod
    def recover_coord(img_split,kps):
        pois = kps.copy()
        row = 2
        col = 4
        y = 0
        for i in range(row):
            x = 0
            for j in range(col):
                pois[i * col + j][:,0:1]+=x
                pois[i * col + j][:,1:2]+=y
                x += img_split[i * col + j].shape[1]
            y+=img_split[i * col + j].shape[0]
        pois = np.concatenate(pois,axis = 0)
        return pois
    @staticmethod
    def copy(src, dst):

        # 目标路径
        dst_path = dst + '\\' + os.path.basename(src)
        # 使用shutil库的copy2函数复制文件
        shutil.copy2(src, dst_path)

    @staticmethod
    def makefolder(path):
        '''
        创建一个文件
        :param path:路径
        :return:
        '''
        folder = os.path.exists(path);
        if not folder:
            os.makedirs(path);

    @staticmethod
    def drawlines(left_img_you, right_img_you, left_nei_kps, right_nei_kps, path=""):
        # time_start1 = time.time()  # 记录开始时间

        trans_left = np.copy(left_nei_kps)
        trans_right = np.copy(right_nei_kps)
        left, right, left_change, right_change = Tools.same_shape(left_img_you, right_img_you)

        show_img = np.concatenate([left, right], 1)
        show_img2 = np.copy(show_img)
        trans_right[:, 0] = trans_right[:, 0] + left.shape[1] + right_change[1]
        trans_right[:, 1] = trans_right[:, 1] + right_change[0]
        trans_left[:, 0] = trans_left[:, 0] + left_change[1]
        trans_left[:, 1] = trans_left[:, 1] + left_change[0]
        i = 0
        trans_left = trans_left.astype(int).tolist()
        trans_right = trans_right.astype(int).tolist()

        for j in range(len(trans_left)):
            show_img = cv2.circle(show_img, tuple(trans_left[j]), 7, (0, 0, 255), 0)
            show_img = cv2.circle(show_img, tuple(trans_right[j]), 7, (0, 0, 255), 0)
            show_img = cv2.line(
                show_img, tuple(trans_left[j]), tuple(trans_right[j]), (0, 255, 0), 1
            )
            show_img2 = cv2.circle(show_img2, tuple(trans_left[j]), 7, (0, 0, 255), 0)
            show_img2 = cv2.circle(show_img2, tuple(trans_right[j]), 7, (0, 0, 255), 0)
            if bool(path):
                Tools.makefolder(path)
                if 10 < i < 30 and i % 20 == 0:
                    cv2.imwrite(path + "\\" + str(i) + "first.jpg", show_img)
            # else:
            #     MyCV2.cv_show('name', show_img)
            i += 1
        i = 0
        # cv_show('name', show_img);
        if bool(path):
            cv2.imwrite(path + "\\result.jpg", show_img)
            cv2.imwrite(path + "\\keypoints.jpg", show_img2)
        else:
            return show_img

    @staticmethod
    def same_shape(left_img_you, right_img_you):
        '''
        将两张图片填充为相同大小（填充的部分用黑色像素）
        :param left_img_you: 左片
        :param right_img_you: 右片
        :return:
        left：调整大小后的左片
        right：调整大小后的右片
        left_change：左片的填充量，是一个list，list[0]=上侧填充的像素值，list[1]为左侧填充的像素值
        right_change：右片填充量
        '''
        left = np.copy(left_img_you)
        right = np.copy(right_img_you)
        left_shape = left.shape
        right_shape = right.shape
        height = max(left_shape[0], right_shape[0])
        width = max(left_shape[1], right_shape[1])
        left_change = [int(np.ceil((height - left_shape[0]) / 2)), int(np.ceil((width - left_shape[1]) / 2))]
        right_change = [int(np.ceil((height - right_shape[0]) / 2)), int(np.ceil((width - right_shape[1]) / 2))]
        left = cv2.copyMakeBorder(left, left_change[0], int((height - left_shape[0]) / 2), left_change[1]
                                  , int((width - left_shape[1]) / 2), cv2.BORDER_CONSTANT)
        right = cv2.copyMakeBorder(right, right_change[0], int((height - right_shape[0]) / 2), right_change[1]
                                   , int((width - right_shape[1]) / 2), cv2.BORDER_CONSTANT)
        return left, right, left_change, right_change

    @staticmethod
    def extract_data(dictInList,key):
        list_data = [i[key] for i in dictInList]
        return np.concatenate(list_data,axis=0)
    @staticmethod
    def split_data(data,key,count=500):
        num = int(len(data)/count) + 1
        values = list(data.values())
        result = []
        for i in range(num):
            if i+1 == num:
                result.append(Tools.extract_data(values[i * count:],key))
                break
            result.append(Tools.extract_data(values[i * count:(i + 1) * count],key))
        return result
    
    # @staticmethod
    # def draw_poi_cloud(pois, pois1, name="", rgb1='', rgb2=""):
    #     point_cloud = o3d.geometry.PointCloud()
    #     # 创建点云对象
    #     point_cloud.points = o3d.utility.Vector3dVector(pois)
    #     point_cloud1 = o3d.geometry.PointCloud()
    #     # 创建点云对象
    #     point_cloud1.points = o3d.utility.Vector3dVector(pois1)
    #     # 输入点云坐标，按行排列
    #     if len(rgb1):
    #         point_cloud.colors = o3d.utility.Vector3dVector(rgb1)
    #     if len(rgb2):
    #         point_cloud1.colors = o3d.utility.Vector3dVector(rgb2)
    #         # rbg/255
    #     o3d.visualization.draw_geometries([point_cloud, point_cloud1], window_name=name)

    @staticmethod
    def extract_data(features,key):
        data = [i[key][0][0] for _,i in features.items()]
if __name__ == '__main__':
    t = Tools()
    t.read_pos(r'I:\zzdx_3dtiles\query_images')


